/*
题目：排序链表
给你链表的头结点 head ，请将其按 升序 排列并返回 排序后的链表 。
 */
public class SortList {
    //归并排序链表
    public ListNode sortList(ListNode head) {
        if (head == null || head.next == null)  return head;

        return mergeSort(head);
    }

    //排序主体
    private ListNode mergeSort(ListNode head) {
        if (head == null || head.next == null) {
            return head;//只有一个元素，返回
        }

        ListNode midNode = searchMidNode(head);
        ListNode next = midNode.next;
        midNode.next = null;

        ListNode left = mergeSort(head);
        ListNode right = mergeSort(next);

        return merge(left, right);
    }

    //归并
    private ListNode merge(ListNode left, ListNode right) {
        ListNode dummy = null;
        if (left.val < right.val) {
            dummy = left;
            left = left.next;
        } else {
            dummy = right;
            right = right.next;
        }

        ListNode ret = dummy;

        while (left != null && right != null) {
            if (left.val < right.val) {
                dummy.next = left;
                left = left.next;
            } else {
                dummy.next = right;
                right = right.next;
            }
            dummy = dummy.next;
        }
        if (left != null) {
            dummy.next = left;
        }
        if (right != null) {
            dummy.next = right;
        }
        return ret;
    }

    //寻找中间节点
    private ListNode searchMidNode(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        ListNode prev = null; //记录上一个节点

        while (fast != null && fast.next != null) {
            prev = slow;
            slow = slow.next;
            fast = fast.next.next;
        }

        return prev;
    }
}
